﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Research.DynamicDataDisplay.Common;
using Microsoft.Research.DynamicDataDisplay;
using Microsoft.Research.DynamicDataDisplay.Charts;
using System.Data.SqlClient;
using System.Data;
using Microsoft.SqlServer.Types;
using System.Data.SqlTypes;

namespace GeometryViewerControl
{
    /// <summary>
    /// Interaction logic for UserControl1.xaml
    /// </summary>
    public partial class GeometryViewerControl : UserControl
    {
        //public string ZoomLevelXText = "qqZoom Level X:";

        public static readonly DependencyProperty ZoomLevelXTextProperty = 
    DependencyProperty.Register(
    "ZoomLevelXText", typeof(string), typeof(GeometryViewerControl));
        public string ZoomLevelXText
        {
            get { return (string)GetValue(ZoomLevelXTextProperty); }
            set { SetValue(ZoomLevelXTextProperty, value); }
        }
        public static readonly DependencyProperty ZoomLevelYTextProperty =
    DependencyProperty.Register(
    "ZoomLevelYText", typeof(string), typeof(GeometryViewerControl));
        public string ZoomLevelYText
        {
            get { return (string)GetValue(ZoomLevelYTextProperty); }
            set { SetValue(ZoomLevelYTextProperty, value); }
        }
        public static readonly DependencyProperty ResetSizeButtonTextProperty =
    DependencyProperty.Register(
    "ResetSizeButtonText", typeof(string), typeof(GeometryViewerControl));
        public string ResetSizeButtonText
        {
            get { return (string)GetValue(ResetSizeButtonTextProperty); }
            set { SetValue(ResetSizeButtonTextProperty, value); }
        }


        public GeometryViewerControl()
        {
            //ZoomLevelXText = "Zoom Level X:";
            InitializeComponent();
            Loaded += new RoutedEventHandler(GeometryViewerControl_Loaded);
        }

        public SqlConnection conn;
        public void ShowGraph(int id)
        {
            try
            {
                conn.Open();
                SqlCommand cmd = conn.CreateCommand();
                cmd.CommandType = CommandType.Text;
                cmd.CommandText = "SELECT graph from Graphs where id =" + id.ToString();
                SqlGeometry g = LoadFromDatabase(cmd);
                GeometryViewer geometryViewer1 = new GeometryViewer(g, Brushes.Black, true);
                //plotter.Children.Clear();
                clearPlotter();
                plotter.Children.Add(geometryViewer1);
                resetPlotter();
                conn.Close();
            }
            catch (SqlException ex)
            {
            }
        }
        public double PairProcessind(int id1, int id2, string processing, double similarityDegree = 0.2)
        {
            if (processing == "similarityDegree")
            {
                try
                {
                    string similarityDegreeString = similarityDegree.ToString().Replace(",", ".");
                    conn.Open();
                    SqlCommand cmd = conn.CreateCommand();
                    cmd.CommandType = CommandType.Text;
                    cmd.CommandText = "SELECT dbo.AdjacencyPolygon(graph, " + similarityDegreeString + ") from Graphs where id =" + id1.ToString();
                    SqlGeometry g1 = LoadFromDatabase(cmd);
                    GeometryViewer geometryViewer1 = new GeometryViewer(g1, Brushes.Blue, true);
                    cmd.CommandText = "SELECT dbo.AdjacencyPolygon(graph, " + similarityDegreeString + ") from Graphs where id =" + id2.ToString();
                    SqlGeometry g2 = LoadFromDatabase(cmd);
                    GeometryViewer geometryViewer2 = new GeometryViewer(g2, Brushes.Red, false);

                    cmd.CommandText = "SELECT [Graphs].[dbo].[SimilarityDegree] (" +
                        "(select graph from Graphs where id = " + id1.ToString() + ")" +
                            ",(select graph from Graphs where id = " + id2.ToString() + ")" +
  "," + similarityDegreeString + ")";
                    object res = cmd.ExecuteScalar();
                    double degree = Convert.ToDouble(res);


                    clearPlotter();
                    plotter.Children.Add(geometryViewer1);
                    plotter.Children.Add(geometryViewer2);
                    resetPlotter();
                    conn.Close();
                    return degree;
                }
                catch (SqlException ex)
                {
                }
            }

            List<int> localIdList = new List<int>();
            localIdList.Add(id1);
            localIdList.Add(id2);
            GroupProcessind(localIdList, processing);
            return 0;
        }

        public void GroupProcessind(List<int> idList, string processing)
        {
            string idListString = string.Join(",", idList.Select(n => n.ToString()).ToArray());

            string functionName = "";
            switch (processing)
            {
                case "average":
                    functionName = "dbo.AverageGraph(dbo.UnionAggregate(graph))";
                    break;
                case "BottomBorder":
                    functionName = "dbo.BottomBorder(dbo.UnionAggregate(graph))";
                    break;
                case "TopBorder":
                    functionName = "dbo.TopBorder(dbo.UnionAggregate(graph))";
                    break;
                case "OuterBorder":
                    functionName = "dbo.OuterBorder(dbo.UnionAggregate(graph))";
                    break;
                default:
                    break;
            }

            try
            {
                conn.Open();
                SqlCommand cmd = conn.CreateCommand();
                cmd.CommandType = CommandType.Text;
                cmd.CommandText = "SELECT " + functionName + " from Graphs where id in(" + idListString + ");";
                SqlGeometry g = LoadFromDatabase(cmd);
                GeometryViewer geometryViewer1 = new GeometryViewer(g, Brushes.Black, true);
                //plotter.Children.Clear();
                clearPlotter();
                plotter.Children.Add(geometryViewer1);
                resetPlotter();
                conn.Close();
            }
            catch (SqlException ex)
            {
            }


        }

        void GeometryViewerControl_Loaded(object sender, RoutedEventArgs e)
        {
            //plotter.Viewport.Visible = new Rect(-0.2, -1.2, 1.4, 2.4);
            /*SqlConnection conn = new SqlConnection("Data Source=(local);Initial Catalog=Graphs;Integrated Security=True");
            SqlCommand cmd1;
            SqlCommand cmd2;
            try
            {
                conn.Open();
                cmd1 = conn.CreateCommand();
                cmd1.CommandType = CommandType.Text;
                cmd1.CommandText = "SELECT dbo.AdjacencyPolygon(graph, 0.2) from Graphs where id =6";
                cmd2 = conn.CreateCommand();
                cmd2.CommandType = CommandType.Text;
                cmd2.CommandText = "SELECT dbo.AdjacencyPolygon(graph, 0.2) from Graphs where id =7";
                SqlGeometry g1 = LoadFromDatabase(cmd1);
                SqlGeometry g2 = LoadFromDatabase(cmd2);

                GeometryViewer geometryViewer1 = new GeometryViewer(g1, Brushes.Blue, true);
                GeometryViewer geometryViewer2 = new GeometryViewer(g2, Brushes.Red, false);
                plotter.Children.Add(geometryViewer1);
                plotter.Children.Add(geometryViewer2);
                conn.Close();
            }
            catch (SqlException ex)
            {

            }*/
            /*Rect sizeRect = geometryViewer1.BoundingBox;
            sizeRect.Union(geometryViewer2.BoundingBox);
            plotter.Viewport.Visible = sizeRect;*/
            resetPlotter();

        }
        private SqlGeometry LoadFromDatabase(SqlCommand cmd)
        {
            using (cmd)
            {
                try
                {
                    using (SqlDataReader rdr = cmd.ExecuteReader())
                    {
                        rdr.Read();

                        int geomCol = 0;
                        if (rdr.FieldCount > 2)
                        {
                            return null;
                        }
                        if (rdr.FieldCount == 2)
                        {
                            geomCol = 1;
                        }

                        if (!(rdr[geomCol] is SqlGeometry))
                        {
                            return null;
                        }
                        do
                        {
                            if (rdr[geomCol] != DBNull.Value)
                            {
                                return (SqlGeometry)rdr[geomCol];
                            }
                        } while (rdr.Read());
                        //txtStatus.Text = string.Format("Fetched {0} records.", count);
                    }
                }
                catch (SqlException ex)
                {
                    //txtStatus.Text = string.Format("Could not execute SQL. The error returned was: {0}", ex.Message);
                }
            }
            return null;
        }
        private void buttonXPlus_Click(object sender, RoutedEventArgs e)
        {
            plotter.Visible = plotter.Visible.ZoomX(plotter.Visible.GetCenter(), 0.9);
        }

        private void buttonXMinus_Click(object sender, RoutedEventArgs e)
        {
            plotter.Visible = plotter.Visible.ZoomX(plotter.Visible.GetCenter(), 1.1);
        }

        private void buttonYPlus_Click(object sender, RoutedEventArgs e)
        {
            plotter.Visible = plotter.Visible.ZoomY(plotter.Visible.GetCenter(), 0.9);
        }

        private void buttonYMinus_Click(object sender, RoutedEventArgs e)
        {
            plotter.Visible = plotter.Visible.ZoomY(plotter.Visible.GetCenter(), 1.1);
        }
        private void resetPlotter()
        {
            Rect sizeRect = new Rect();
            foreach (var child in plotter.Children)
            {
                if (child.GetType() == typeof(GeometryViewer))
                {
                    GeometryViewer gv = (GeometryViewer)child;
                    sizeRect.Union(gv.BoundingBox);
                }
            }
            plotter.Viewport.Visible = sizeRect;
        }
        private void clearPlotter()
        {
            List<GeometryViewer> viewers = new List<GeometryViewer>();
            foreach (var child in plotter.Children)
            {
                if (child.GetType() == typeof(GeometryViewer))
                {
                    viewers.Add((GeometryViewer)child);
                    //plotter.Children.Remove(child);
                }
            }
            foreach (GeometryViewer viewer in viewers)
                plotter.Children.Remove(viewer);
        }

        private void btnClear_Click(object sender, RoutedEventArgs e)
        {
            resetPlotter();
        }
    }
}
